const path = require('path');
const fs = require('fs-extra');
const getData = require('./getData');

class Base {
    constructor(option) {
        // 每个base对应一个 json文件
        this.path = option.jsonFile;
        this.basePath = option.basePath;
        this.encoding = option.encoding || 'utf-8';
        this.filePath = path.join(this.basePath, this.path);
        this.data = {};
        this.setTimer = null;

        try {
            fs.accessSync(this.filePath, fs.constants.W_OK | fs.constants.R_OK)
            this.readFileData();
        }
        catch(e) {
            this.createData();
        }
    }

    getType(data) {
        let type = Object.prototype.toString.call(data);

        type = type.slice(8, type.length - 1);

        return type;
    }

    createData() {
        fs.outputFileSync(this.filePath, JSON.stringify({}))
    }

    readFileData() {
        let content = '';
        
        try {
            content = fs.readFileSync(this.filePath, {
                encoding: this.encoding
            })
        }
        catch(e) {
            console.log('READ JSON Error: ', e);
        }

        try {
            let jsonData = null;

            if(content) {
                jsonData = JSON.parse(content);
            }
            else {
                jsonData = {}
            }
            Object.assign(this.data, jsonData);
        }
        catch(e) {
            console.log('PARSE JSON Error ', e);
        }
    }

    delete(key) {
        let result = {success: true};

        if(typeof key === 'string') {
            if(key in this.data) {
                delete this.data[key];
            }
        }
        else if(Object.prototype.toString.call(key) === '[object Array]') {
            key.forEach((delKey) => {
                if(key in this.data) {
                    delete this.data[delKey];
                }
            });
        }
        else {
            this.data = {};
        }

        this.set(this.data);

        return Promise.resolve(result);
    }

    get(key, deep) {
        return new Promise((resolve, reject) => {
            let returnData = null;
            
            if(typeof key === 'string') {
                if (deep) {
                    returnData = getData(this.data, key);
                }
                else {
                    returnData = this.data[key];
                }
            }
            else if(this.getType(key) === 'Array') {
                let result = [];
    
                key.forEach((item) => {
                    if (deep) {
                        result.push(getData(this.data, item));
                    }
                    else {
                        result.push(this.data[item]);
                    }
                });
    
                returnData = result;
            }
            else {
                returnData = this.data;
            }

            resolve(returnData);
        });   
    }

    set(args1, args2) {
        if (!this.changed) {
            this.changed = {};
        }
        if(args2 === undefined) {
            if(this.getType(args1) === 'Object') {
                Object.keys(args1)
                    .forEach((key) => {
                        // 此处区分下是a.b形势吗
                        if (key.includes('.') || key.includes('[')) {
                            const arr = key.split(/[\.\[]/);
                            let currentKey = '';
                            let currentObj = this.data;
                            let lastKey = arr.pop();
                            lastKey = lastKey.replace(']', '');

                            arr.forEach((item) => {
                                let isArray = false;

                                currentKey = item;
                                
                                if (currentKey.charAt(currentKey.length - 1) === ']') {
                                    isArray = true;
                                    currentKey = currentKey.substring(0, currentKey.length - 1);
                                }

                                if (typeof currentObj[currentKey] !== 'object') {
                                    currentObj[currentKey] = isArray ? [] : {};
                                }

                                currentObj = currentObj[currentKey];
                            });

                            currentObj[lastKey] = args1[key];
                        } else {
                            this.changed[key] = this.data[key];
                            this.data[key] = args1[key];
                        }
                    });
            }
            else {
                throw new Error('如果只传一个参数，必须传入一个对象');
            }
        }
        else {
            this.changed[args1] = this.data[args1];
            this.data[args1] = args2;
        }

        return new Promise((resolve, reject) => {
            clearTimeout(this.setTimer);
            this.setTimer = setTimeout(() => {
                this.writeFileData(resolve, reject);
            }, 100);
        });
    }

    writeFileData(resolve, reject) {
        fs.outputFile(this.filePath, JSON.stringify(this.data, null, '\t'), {
            encoding: this.encoding
        }, (err) => {
            if(err) {
                reject(err)
            }
            else {
                resolve(this.data);
            }
        });
    }
}


module.exports = Base;